package com.education.platform.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.education.platform.dto.notification.NotificationCreateDTO;
import com.education.platform.entity.Notification;
import com.education.platform.entity.User;
import com.education.platform.exception.BusinessException;
import com.education.platform.mapper.NotificationMapper;
import com.education.platform.mapper.UserMapper;
import com.education.platform.service.NotificationService;
import com.education.platform.service.MessageService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 通知服务实现
 *
 * @author education-platform
 * @since 2025-10-27
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class NotificationServiceImpl implements NotificationService {

    private final NotificationMapper notificationMapper;
    private final UserMapper userMapper;
    private final MessageService messageService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createNotification(NotificationCreateDTO dto) {
        Notification notification = new Notification();
        notification.setTitle(dto.getTitle());
        notification.setContent(dto.getContent());
        notification.setType(dto.getType());
        notification.setPriority(dto.getPriority());
        notification.setTargetUsers(dto.getTargetUsers());
        notification.setUserIds(dto.getUserIds());
        notification.setLinkUrl(dto.getLinkUrl());
        notification.setScheduled(dto.getScheduled());
        notification.setSendTime(dto.getSendTime());
        notification.setStatus("DRAFT");
        notification.setSendCount(0);
        notification.setReadCount(0);
        
        try {
            notification.setCreatedBy(StpUtil.getLoginIdAsLong());
        } catch (Exception e) {
            notification.setCreatedBy(null);
        }

        notificationMapper.insert(notification);
        return notification.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateNotification(Long id, NotificationCreateDTO dto) {
        Notification notification = getNotificationById(id);
        if (!"DRAFT".equals(notification.getStatus())) {
            throw new BusinessException("只能编辑草稿状态的通知");
        }

        notification.setTitle(dto.getTitle());
        notification.setContent(dto.getContent());
        notification.setType(dto.getType());
        notification.setPriority(dto.getPriority());
        notification.setTargetUsers(dto.getTargetUsers());
        notification.setUserIds(dto.getUserIds());
        notification.setLinkUrl(dto.getLinkUrl());
        notification.setScheduled(dto.getScheduled());
        notification.setSendTime(dto.getSendTime());

        notificationMapper.updateById(notification);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteNotification(Long id) {
        Notification notification = getNotificationById(id);
        if (!"DRAFT".equals(notification.getStatus())) {
            throw new BusinessException("只能删除草稿状态的通知");
        }
        notificationMapper.deleteById(id);
    }

    @Override
    public Notification getNotificationById(Long id) {
        Notification notification = notificationMapper.selectById(id);
        if (notification == null) {
            throw new BusinessException("通知不存在");
        }
        return notification;
    }

    @Override
    public IPage<Notification> getNotificationPage(Page<Notification> page, String type, String status, String keyword) {
        LambdaQueryWrapper<Notification> wrapper = new LambdaQueryWrapper<>();
        
        if (StringUtils.hasText(type)) {
            wrapper.eq(Notification::getType, type);
        }
        if (StringUtils.hasText(status)) {
            wrapper.eq(Notification::getStatus, status);
        }
        if (StringUtils.hasText(keyword)) {
            wrapper.and(w -> w.like(Notification::getTitle, keyword)
                    .or().like(Notification::getContent, keyword));
        }
        
        wrapper.orderByDesc(Notification::getCreatedAt);
        
        return notificationMapper.selectPage(page, wrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void sendNotification(Long id) {
        Notification notification = getNotificationById(id);
        
        // 如果是定时发送且时间未到，状态改为PENDING
        if (notification.getScheduled() && notification.getSendTime() != null 
                && notification.getSendTime().isAfter(LocalDateTime.now())) {
            notification.setStatus("PENDING");
            notificationMapper.updateById(notification);
            log.info("通知设置为定时发送，通知ID: {}, 发送时间: {}", id, notification.getSendTime());
            return;
        }

        // 获取目标用户列表
        List<Long> targetUserIds = getTargetUserIds(notification);
        
        if (targetUserIds.isEmpty()) {
            throw new BusinessException("没有找到目标用户");
        }
        
        // 构建扩展数据
        String extraData = String.format("{\"notificationId\":%d,\"type\":\"%s\",\"priority\":\"%s\",\"linkUrl\":\"%s\"}", 
                notification.getId(), 
                notification.getType(), 
                notification.getPriority(),
                notification.getLinkUrl() != null ? notification.getLinkUrl() : "");
        
        // 发送系统消息到小程序
        int successCount = 0;
        for (Long userId : targetUserIds) {
            try {
                messageService.sendSystemMessage(
                    userId, 
                    notification.getTitle(), 
                    notification.getContent(),
                    extraData
                );
                successCount++;
            } catch (Exception e) {
                log.error("发送通知消息失败，用户ID: {}, 错误: {}", userId, e.getMessage());
            }
        }
        
        // 更新通知状态
        notification.setStatus("SENT");
        notification.setSentAt(LocalDateTime.now());
        notification.setSendCount(successCount);
        notificationMapper.updateById(notification);
        
        log.info("通知发送完成，通知ID: {}, 目标用户数: {}, 成功发送: {}", id, targetUserIds.size(), successCount);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchSendNotifications(List<Long> ids) {
        int successCount = 0;
        int failCount = 0;
        
        for (Long id : ids) {
            try {
                sendNotification(id);
                successCount++;
            } catch (Exception e) {
                failCount++;
                log.error("批量发送通知失败，通知ID: {}, 错误: {}", id, e.getMessage());
            }
        }
        
        log.info("批量发送通知完成，总数: {}, 成功: {}, 失败: {}", ids.size(), successCount, failCount);
    }

    @Override
    public Map<String, Object> getNotificationStats() {
        return notificationMapper.getNotificationStats();
    }

    @Override
    public List<Notification> getUserUnreadNotifications(Long userId) {
        // TODO: 实现用户未读通知查询
        LambdaQueryWrapper<Notification> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Notification::getStatus, "SENT");
        wrapper.orderByDesc(Notification::getSentAt);
        wrapper.last("LIMIT 10");
        return notificationMapper.selectList(wrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void markAsRead(Long notificationId, Long userId) {
        // TODO: 实现标记已读逻辑
        notificationMapper.updateReadCount(notificationId);
    }

    /**
     * 获取目标用户ID列表
     */
    private List<Long> getTargetUserIds(Notification notification) {
        String targetUsers = notification.getTargetUsers();
        
        if ("ALL".equals(targetUsers)) {
            // 所有用户
            return userMapper.selectList(null).stream()
                    .map(User::getId)
                    .collect(Collectors.toList());
        } else if ("TEACHER".equals(targetUsers)) {
            // 所有教员
            LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
            wrapper.like(User::getRoles, "TEACHER");
            return userMapper.selectList(wrapper).stream()
                    .map(User::getId)
                    .collect(Collectors.toList());
        } else if ("PARENT".equals(targetUsers)) {
            // 所有家长
            LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
            wrapper.like(User::getRoles, "PARENT");
            return userMapper.selectList(wrapper).stream()
                    .map(User::getId)
                    .collect(Collectors.toList());
        } else if ("CUSTOM".equals(targetUsers) && StringUtils.hasText(notification.getUserIds())) {
            // 指定用户
            return Arrays.stream(notification.getUserIds().split(","))
                    .map(String::trim)
                    .map(Long::parseLong)
                    .collect(Collectors.toList());
        }
        
        return List.of();
    }
}

